from PyQt6.QtWidgets import * 
from PyQt6.QtGui import *
from PyQt6.QtCore import *
from GUI.MainWindow import Ui_MainWindow
from GUI.Start import Ui_Form
from GUI.WorkSpace import Ui_Form as WorkSpace
from GUI.MyWorkSpace import MyWorkSpace
import GUI.icons
import cv2
import json
import datetime
import os


class Frame():
    def __init__(self, img_path, name):
        self.img_path = img_path
        self.name = name
        self.cv2_img = cv2.imread(img_path)
        QImageReader.setAllocationLimit(104857600)
        self.qt_img = QImage(img_path)

class CustomListItem(QWidget):
    def __init__(self, icon_path, name, open_time, parent=None):
        super().__init__(parent)
        
        # 主布局，横向布局
        main_layout = QHBoxLayout(self)
        main_layout.setContentsMargins(5, 5, 5, 5)
        main_layout.setSpacing(10)
        
        # 图标
        icon_label = QLabel(self)
        pixmap = QPixmap(icon_path)
        icon_label.setPixmap(pixmap.scaledToHeight(24))
        main_layout.addWidget(icon_label)
        
        # 名称和时间的垂直布局
        detail_layout = QVBoxLayout()
        detail_layout.setContentsMargins(0, 0, 0, 0)
        detail_layout.setSpacing(2)
        
        # 名称标签
        name_label = QLabel(name)
        name_label.setObjectName('name_label')
        name_label.setFont(QFont('Arial', 13))
        # 设置文本颜色
        name_label.setStyleSheet('color: #333;')
        # 右对齐
        name_label.setAlignment(Qt.AlignmentFlag.AlignRight)
        detail_layout.addWidget(name_label)
        
        # 时间标签
        time_label = QLabel(open_time.split('.')[0])
        time_label.setFont(QFont('Arial', 10))
        # 设置文本颜色
        time_label.setStyleSheet('color: #666;')
        # 右对齐
        time_label.setAlignment(Qt.AlignmentFlag.AlignRight)
        detail_layout.addWidget(time_label)
        
        main_layout.addLayout(detail_layout)
        self.setLayout(main_layout)
    
    def sizeHint(self):
        return QSize(0, 50)
    
class WorkSpaceWidget(QWidget):
    def __init__(self):
        super().__init__()

    def find_graphics_view(self):
        """
        查找给定QWidget是否包含QGraphicsView。
        
        :param widget: 要检查的QWidget实例。
        :return: 如果找到QGraphicsView，则返回第一个找到的QGraphicsView实例，否则返回None。
        """
        for child in self.findChildren(QWidget):
            if isinstance(child, QGraphicsView):
                return child
        return None

class MyWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        # 创建一个中央Widget
        central_widget = QWidget(self)
        self.setCentralWidget(central_widget)
        # 创建一个垂直布局
        self.layout = QVBoxLayout(central_widget)
        # 新建欢迎界面
        self.Form = QWidget()
        self.layout.addWidget(self.Form)
        self.start = Ui_Form()
        self.start.setupUi(self.Form)
        self.start_animation()
        # 阴影
        shadow_effect = QGraphicsDropShadowEffect(self.start.listWidget)
        shadow_effect.setBlurRadius(15)  # 阴影模糊半径
        shadow_effect.setColor(Qt.GlobalColor.darkGray)  # 阴影颜色
        shadow_effect.setOffset(0, 0)  # 阴影偏移量，正数表示外阴影，0,0 表示内阴影
        self.start.listWidget.setGraphicsEffect(shadow_effect)  # 将阴影效果应用到 QListWidget
        # 新建workspace界面
        self.ws = WorkSpaceWidget()
        self.ws_ui = WorkSpace()
        self.ws_ui.setupUi(self.ws)
        # 为工具栏toolBox添加阴影
        shadow_effect = QGraphicsDropShadowEffect(self.ws_ui.toolBox)
        shadow_effect.setBlurRadius(15)  # 阴影模糊半径
        shadow_effect.setColor(Qt.GlobalColor.darkGray)
        shadow_effect.setOffset(0, 0)
        self.ws_ui.toolBox.setGraphicsEffect(shadow_effect)
        # 定义画布
        self.scene = QGraphicsScene()  # 创建画布
        self.ws_ui.graphicsView.setScene(self.scene)  # 把画布添加到窗口
        self.ws_ui.graphicsView.show()
        # 设置当前页面和待标注图像
        self.current_page = 0
        self.frame = None
        # 设置标题
        self.setWindowTitle("病理切片标注系统")
        # 浏览历史记录
        self.filename = './Logs/history.json'
        self.load_history()
        # 添加信号槽
        self.start.pushButton.clicked.connect(self.open_local)
        self.start.pushButton_2.clicked.connect(self.open_server)
        self.start.listWidget.itemClicked.connect(self.on_list_item_clicked)

    # 列表项点击事件
    def on_list_item_clicked(self, item):
        # 获取列表项的小部件
        widget = self.start.listWidget.itemWidget(item)
        # 获取小部件的子部件
        label = widget.findChild(QLabel, 'name_label')
        # 获取标签的文本
        path = label.text()
        # 关闭start界面
        self.Form.close()
        # 打开工作区
        self.open_workspace(file_path=path)
        new_data = {"filename": path, "opened_at": datetime.datetime.now().isoformat()}
        try:
            # 尝试读取现有文件
            with open(self.filename, 'r') as f:
                if os.stat(self.filename).st_size == 0:
                    existing_data = []
                else:
                    existing_data = json.load(f)
        except FileNotFoundError:
            # 如果文件不存在，初始化为空列表
            existing_data = []
        
        # 将新数据与现有数据合并
        for existing in existing_data:
            if new_data['filename'] == existing['filename']:
                existing_data.remove(existing)
                break   
        all_data = existing_data + [new_data]  
        # 将合并后的列表转换为JSON字符串
        json_data = json.dumps(all_data, indent=4)
        
        # 写入JSON数据到文件
        with open(self.filename, 'w') as f:
            f.write(json_data)



    def open_local(self):
        # 打开文件对话框，选择多个JPG文件
        file_dialog = QFileDialog(self)
        file_dialog.setNameFilter("Images (*.jpg *tif)")
        file_dialog.setFileMode(QFileDialog.FileMode.ExistingFiles)
        file_dialog.setOption(QFileDialog.Option.DontUseNativeDialog, False)  # 使用原生文件对话框

        if file_dialog.exec():
            files = file_dialog.selectedFiles()
            # 获取当前时间,并转换为ISO格式,精确到秒
            current_time = datetime.datetime.now().isoformat()
            # 创建一个列表来存储文件名及其打开时间
            new_data_list = [{"filename": file, "opened_at": current_time} for file in files]                   
            try:
                # 尝试读取现有文件
                with open(self.filename, 'r') as f:
                    if os.stat(self.filename).st_size == 0:
                        existing_data = []
                    else:
                        existing_data = json.load(f)
            except FileNotFoundError:
                # 如果文件不存在，初始化为空列表
                existing_data = []
            
            # 将新数据与现有数据合并
            for new_data in new_data_list:
                for existing in existing_data:
                    if new_data['filename'] == existing['filename']:
                        existing_data.remove(existing)
                        break   
            all_data = existing_data + new_data_list  
            # 将合并后的列表转换为JSON字符串
            json_data = json.dumps(all_data, indent=4)
            
            # 写入JSON数据到文件
            with open(self.filename, 'w') as f:
                f.write(json_data)
            # 关闭start界面 
            self.Form.close()
            # 打开工作区
            self.open_workspace(file_path=files[0])


    def open_server(self):
        pass

    def resizeEvent(self, event):
        # 调用基类的 resizeEvent 方法，处理原始的事件
        super().resizeEvent(event)

        # 获取新的窗口大小
        new_size = event.size()
        old_size = event.oldSize()

        # 在这里可以添加任何需要在窗口大小变化时执行的代码
        # 例如，更新布局，重新绘制界面元素等
        self.ws_ui.graphicsView.setGeometry(0, 0, new_size.width(), new_size.height())
        # 修改toobox的位置
        width = self.ws_ui.toolBox.width()
        height = self.ws_ui.toolBox.height()
        posy = self.ws_ui.toolBox.y()
        self.ws_ui.toolBox.setGeometry(new_size.width()//2- width // 2, posy, width, height)


    def load_history(self):      
        try:
            # 尝试读取现有文件
            with open(self.filename, 'r') as f:
                # 判断文件是否为空
                if os.stat(self.filename).st_size == 0:
                    return
                existing_data = json.load(f)
                for i in range(len(existing_data)-1, -1, -1):
                    path = existing_data[i]['filename']
                    time = existing_data[i]['opened_at']
                    name = path.split('/')[-1]
                    temp_file_path = f'./Temp/icons/{name}'
                    cache_imgs = os.listdir('./Temp/icons/')
                    if name in cache_imgs:
                        item = CustomListItem(temp_file_path, path, time)
                        list_item = QListWidgetItem(self.start.listWidget)
                        # 设置大小
                        list_item.setSizeHint(item.sizeHint())
                        
                        self.start.listWidget.setItemWidget(list_item, item)
                        continue
                    # 使用OpenCV读取图片
                    img = cv2.imread(path)

                    # 获取图片的宽度和高度
                    height, width = img.shape[:2]

                    # 计算新的高度，以保持长宽比不变
                    new_height = int(40 * height / width)

                    # 调整图片大小
                    resized_img = cv2.resize(img, (40, new_height))

                    # 将调整大小后的图片保存到临时文件
                    cv2.imwrite(temp_file_path, resized_img)

                    # 从临时文件中加载图片
                    item = CustomListItem(temp_file_path, name, time)
                    list_item = QListWidgetItem(self.start.listWidget)
                    list_item.setSizeHint(item.sizeHint())
                    self.start.listWidget.setItemWidget(list_item, item)
        except FileNotFoundError:
            return

    def start_animation(self):
        # 创建动画
        self.animation = QPropertyAnimation(self, b'windowOpacity')
        self.animation.setDuration(1000)  # 动画持续时间
        self.animation.setStartValue(0.0)  # 开始时的透明度
        self.animation.setEndValue(1.0)  # 结束时的透明度
        easing_curve = QEasingCurve(QEasingCurve.Type.InOutQuart)
        self.animation.setEasingCurve(easing_curve)
        self.animation.start()  # 启动动画


    def open_workspace(self, **kwargs):
        self.layout.addWidget(self.ws)
        # 从参数中获取文件路径
        file_path = kwargs.get('file_path')
        name = file_path.split('/')[-1]
        # 创建一个Frame对象
        self.frame = Frame(file_path, name)
        # 更新窗口
        self.update_window()

    def update_window(self):
        self.scene.clear()  # 先清空上次的残留
        pix = QPixmap.fromImage(self.frame.qt_img)
        pixmap_item = QGraphicsPixmapItem(pix)
        pixmap_item.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True)
        self.scene.addItem(pixmap_item)
        self.ws_ui.graphicsView.setScene(self.scene)
        # 调整图片高度和窗口高度一致
        self.ws_ui.graphicsView.fitInView(pixmap_item, Qt.AspectRatioMode.KeepAspectRatio)
        
        



